package com.android.widget;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Relin
 * on 2018-11-23.
 * 思维导图控件
 */
public class ThinkMapView extends View {

    /**
     * 控件宽度
     */
    private float width;
    /**
     * 控件高度
     */
    private float height;
    /**
     * 画笔
     */
    private Paint paint;
    /**
     * 线颜色
     */
    private int lineColor = Color.parseColor("#29CA61");
    /**
     * 线的粗细
     */
    private int lineStroke = 2;
    /**
     * 横向间隔
     */
    private float horizontalSpace = 80;
    /**
     * 竖向间隔
     */
    private float verticalSpace = 40;
    /**
     * 节点内间距
     */
    private float nodePadding = 20;
    /**
     * 源节点
     */
    private ThinkNode originNode;

    /**
     * 按下的坐标
     */
    private float downX, downY;
    /**
     * 移动坐标
     */
    private float moveX, moveY;
    /**
     * 字体大小
     */
    private float textSize = 30;
    /**
     * 所有节点数据
     */
    private List<ThinkNode> nodeList;
    /**
     * 节点的高度
     */
    private float nodeHeight = 65;
    /**
     * 屏幕的宽高
     */
    private float screenWidth, screenHeight;
    /**
     * 一级节点上方高度
     */
    private float firstLevelTopHeight = 0F;
    /**
     * 一级节点下方高度
     */
    private float firstLevelBelowHeight = 0F;

    private ThinkNode clickNode;

    public ThinkMapView(Context context) {
        super(context);
        initAttrs(context, null, 0);
    }

    public ThinkMapView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initAttrs(context, attrs, 0);
    }

    public ThinkMapView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initAttrs(context, attrs, defStyleAttr);
    }

    private void initAttrs(Context context, AttributeSet attrs, int defStyleAttr) {
        nodeList = new ArrayList<>();
        paint = new Paint();
        paint.setAntiAlias(true);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        Log.e(this.getClass().getSimpleName(), "onMeasure");
        setMeasuredDimension(Integer.MAX_VALUE / 2, Integer.MAX_VALUE / 2);
        screenWidth = getResources().getDisplayMetrics().widthPixels;
        screenHeight = getResources().getDisplayMetrics().heightPixels;
        setTranslationY(-height / 2 + screenHeight / 2);
        width = getMeasuredWidth();
        height = getMeasuredHeight();
        if (originNode == null) {
            originNode = createNode(null, "1-0", 1, 50, height / 2, 0, "源节点", true, true);
            nodeList.add(originNode);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.e(this.getClass().getSimpleName(), "onDraw");
        if (originNode != null) {
            drawNode(canvas, originNode);
        }
        drawNodes(canvas, originNode);
    }

    /**
     * 获取源节点
     *
     * @return
     */
    public ThinkNode getOriginNode() {
        return originNode;
    }

    /**
     * 绘制节点
     *
     * @param canvas
     * @param parent
     */
    private void drawNodes(Canvas canvas, ThinkNode parent) {
        int count = parent.getChildren().size();
        if (count != 0) {
            for (int i = 0; i < count; i++) {
                ThinkNode child = parent.getChildren().get(i);
                drawNode(canvas, child);
                //绘制子节点和父节点的连线
                drawLine(canvas, parent, child);
                //递归子节点所有节点
                if (child.getChildren().size() != 0) {
                    drawNodes(canvas, child);
                }
            }
        }
    }

    /**
     * 绘制节点
     *
     * @param canvas 画布
     * @param node   节点
     */
    private void drawNode(Canvas canvas, ThinkNode node) {
        //先绘制背景
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(node.getBackground());
        RectF rectF = new RectF(node.getLtX(), node.getLtY(), node.getRbX(), node.getRbY());
        canvas.drawRoundRect(rectF, node.getRadius(), node.getRadius(), paint);
        //绘制文字
        paint.setColor(node.getTextColor());
        paint.setTextSize(node.getTextSize());
        canvas.drawText(node.getText(), node.getX(), node.getY(), paint);
    }

    /**
     * 绘制连线
     *
     * @param canvas 画布
     * @param parent 父节点
     * @param child  子节点
     */
    private void drawLine(Canvas canvas, ThinkNode parent, ThinkNode child) {
        paint.setStrokeWidth(lineStroke);
        paint.setColor(lineColor);
        paint.setStyle(Paint.Style.STROKE);
        float pw = parent.getWidth();
        float ph = parent.getHeight();
        float startX = parent.getLtX() + pw;
        float startY = parent.getLtY() + ph / 2;
        float ch = child.getHeight();
        float endX = child.getLtX();
        float endY = child.getLtY() + ch / 2;
        //控制坐标
        float controlX;
        float controlY;
        if (child.isHorizontal()) {
            controlX = endX;
            controlY = endY = startY;
        } else {
            controlX = startX;
            controlY = endY;
        }
        //绘制弧线
        Path path = new Path();
        path.moveTo(startX, startY);
        path.cubicTo(startX, startY, controlX, controlY, endX, endY);
        canvas.drawPath(path, paint);
    }

    /**
     * 创建节点对象
     *
     * @param parent       父节点
     * @param id           节点ID
     * @param level        节点级数
     * @param x            节点坐标X
     * @param y            节点坐标Y
     * @param position     节点位置
     * @param nodeText     节点文字
     * @param isOrigin     是否是源节点
     * @param isHorizontal 是否是和父节点同水平线上的节点
     */
    private ThinkNode createNode(ThinkNode parent, String id, int level, float x, float y, int position, String nodeText, boolean isOrigin, boolean isHorizontal) {
        ThinkNode node = new ThinkNode();
        node.setId(id);
        node.setLevel(level);
        node.setPosition(position);

        node.setOrigin(isOrigin);
        node.setParent(parent);
        node.setText(nodeText);
        node.setTextSize(textSize);
        node.setHorizontal(isHorizontal);
        float[] wh = measureText(node.getText());
        float offset = nodeHeight / 2 - wh[1] / 2;
        node.setPadding(offset);
        node.setTextWith(wh[0]);
        node.setTextHeight(wh[1]);
        node.setX(x);
        node.setY(y);

        node.setLtX(node.getX() - node.getPadding());
        node.setLtY(node.getY() - wh[1] - node.getPadding());
        node.setRbX(node.getX() + wh[0] + node.getPadding());
        node.setRbY(node.getY() + node.getPadding());
        node.setWidth(node.getRbX() - node.getLtX());
        node.setHeight(node.getRbY() - node.getLtY());

        if (parent != null) {
            if (parent.isOrigin()) {
                node.setFirstLevelNode(node);
            } else {
                node.setFirstLevelNode(parent.getFirstLevelNode());
            }
        }

        if (parent != null) {
            node.setHorizontalY(parent.getY());
        } else {
            node.setHorizontalY(node.getY());
        }

        return node;
    }

    /**
     * 测量字体
     *
     * @param text
     * @return 宽高
     */
    private float[] measureText(String text) {
        paint.setTextSize(textSize);
        Rect rect = new Rect();
        paint.getTextBounds(text, 0, text.length(), rect);
        return new float[]{rect.width(), rect.height()};
    }

    /**
     * 修改节点
     *
     * @param thinkNode    节点
     * @param id           ID
     * @param level        等级
     * @param x            x
     * @param y            y
     * @param offsetTop    offsetTop
     * @param offsetBelow  offsetBelow
     * @param position     position
     * @param isHorizontal 是否是和父节点同水平线上的节点
     * @return
     */
    private void modifyNode(ThinkNode thinkNode, String id, int level, float x, float y, float offsetTop, float offsetBelow, int position, boolean isHorizontal) {
        if (thinkNode == null) {
            return;
        }
        thinkNode.setId(id);
        thinkNode.setLevel(level);
        thinkNode.setPosition(position);
        thinkNode.setHorizontal(isHorizontal);
        thinkNode.setX(x);
        thinkNode.setY(y);
        thinkNode.setOffsetTop(offsetTop);
        thinkNode.setOffsetBelow(offsetBelow);
        thinkNode.setLtX(thinkNode.getX() - thinkNode.getPadding());
        thinkNode.setLtY(thinkNode.getY() - thinkNode.getTextHeight() - thinkNode.getPadding());
        thinkNode.setRbX(thinkNode.getX() + thinkNode.getTextWith() + thinkNode.getPadding());
        thinkNode.setRbY(thinkNode.getY() + thinkNode.getPadding());
        thinkNode.setWidth(thinkNode.getRbX() - thinkNode.getLtX());
        thinkNode.setHeight(thinkNode.getRbY() - thinkNode.getLtY());
        if (thinkNode.getParent() != null) {
            thinkNode.setHorizontalY(thinkNode.getParent().getY());
        }
        if (thinkNode.getChildren().size() != 0) {
            modifyChildren(thinkNode);
        }
    }

    /**
     * 修改子节点
     *
     * @param thinkNode
     */
    private void modifyChildren(ThinkNode thinkNode) {
        if (thinkNode == null) {
            return;
        }
        List<ThinkNode> children = thinkNode.getChildren();
        int childCount = children.size();
        switch (childCount) {
            case 0:
                break;
            case 1:
                ThinkNode fistNode = children.get(0);
                modifyNode(fistNode, fistNode.getId(), fistNode.getLevel(), fistNode.getX(), thinkNode.getY(), 0, 0, fistNode.getPosition(), true);
                break;
            case 2:
                //上方节点
                ThinkNode upNode = children.get(0);
                modifyNode(upNode, upNode.getId(), upNode.getLevel(), upNode.getX(), thinkNode.getY() - upNode.getHeight() - upNode.getPadding() - verticalSpace - upNode.getPadding() + upNode.getPadding() * 2, 0, 0, 0, false);
                //下方节点
                ThinkNode downNode = children.get(1);
                modifyNode(downNode, downNode.getId(), downNode.getLevel(), downNode.getX(), thinkNode.getY() + upNode.getPadding() + verticalSpace + thinkNode.getPadding() + thinkNode.getHeight() - thinkNode.getPadding() * 2, 0, 0, 1, false);
                break;
            default:
                //确定中间节点
                int middleIndex = childCount / 2 + (childCount % 2 == 0 ? -1 : 0);
                ThinkNode middleNode = thinkNode.getChildren().get(middleIndex);
                modifyNode(middleNode, middleNode.getId(), middleNode.getLevel(), thinkNode.getX() + thinkNode.getWidth() + horizontalSpace, thinkNode.getY(), middleIndex, 0, middleIndex, true);
                //上方节点
                for (int i = middleIndex - 1; i > -1; i--) {
                    ThinkNode preNode = thinkNode.getChildren().get(i + 1);
                    ThinkNode node = thinkNode.getChildren().get(i);
                    modifyNode(node, node.getId(), node.getLevel(), preNode.getX(), preNode.getY() - preNode.getHeight() + preNode.getPadding() - verticalSpace - node.getPadding(), 0, 0, i, false);
                }
                //下方节点
                for (int i = middleIndex + 1; i < childCount; i++) {
                    ThinkNode preNode = thinkNode.getChildren().get(i - 1);
                    ThinkNode node = thinkNode.getChildren().get(i);
                    modifyNode(node, node.getId(), node.getLevel(), node.getX(), preNode.getY() + preNode.getPadding() + verticalSpace + node.getPadding() + node.getHeight() - nodePadding * 2, 0, 0, i, false);
                }
                break;
        }
    }

    /**
     * 添加子节点
     *
     * @param parent    父节点
     * @param childText 节点名称
     */
    public void addChildNode(ThinkNode parent, String childText) {
        if (parent == null) {
            return;
        }
        List<ThinkNode> children = parent.getChildren();
        int childCount = children.size();
        float[] wh = measureText(childText);
        switch (childCount) {
            case 0://判断是否有子节点
                ThinkNode horizontalChild = createNode(parent, (parent.getLevel() + 1) + "-0", parent.getLevel() + 1, parent.getX() + parent.getWidth() + horizontalSpace, parent.getY(), 0, childText, false, true);
                parent.getChildren().add(horizontalChild);
                nodeList.add(horizontalChild);
                break;
            case 1://绘制2个子节点的情况
                //上方节点
                ThinkNode upNode = children.get(0);
                modifyNode(upNode, (parent.getLevel() + 1) + "-0", parent.getLevel() + 1, upNode.getX(), parent.getY() - upNode.getHeight() + upNode.getPadding() - verticalSpace - upNode.getPadding(), 0, 0, upNode.getPosition(), false);
                nodeList.add(upNode);
                ThinkNode downNode = createNode(parent, (parent.getLevel() + 1) + "-1", parent.getLevel() + 1, upNode.getX(), parent.getY() + parent.getPadding() + verticalSpace + upNode.getPadding() + wh[1], 1, childText, false, false);
                parent.getChildren().add(downNode);
                nodeList.add(downNode);
                break;
            default:
                //确定中间节点
                int middleIndex = childCount / 2;
                ThinkNode middleNode = parent.getChildren().get(middleIndex);
                modifyNode(middleNode, (parent.getLevel() + 1) + "-" + middleIndex, parent.getLevel() + 1, parent.getX() + parent.getWidth() + horizontalSpace, parent.getY(), 0, 0, middleIndex, true);
                nodeList.add(middleNode);
                //上方节点
                for (int i = middleIndex - 1; i > -1; i--) {
                    ThinkNode preNode = parent.getChildren().get(i + 1);
                    ThinkNode node = parent.getChildren().get(i);
                    modifyNode(node, (parent.getLevel() + 1) + "-" + i, parent.getLevel() + 1, preNode.getX(), preNode.getY() - preNode.getHeight() + preNode.getPadding() - verticalSpace - node.getPadding(), 0, 0, i, false);
                    nodeList.add(node);
                }
                //下方节点
                for (int i = middleIndex + 1; i < childCount; i++) {
                    ThinkNode preNode = parent.getChildren().get(i - 1);
                    ThinkNode node = parent.getChildren().get(i);
                    modifyNode(node, (parent.getLevel() + 1) + "-" + i, parent.getLevel() + 1, node.getX(), preNode.getY() + preNode.getPadding() + verticalSpace + node.getPadding() + node.getHeight() - nodePadding * 2, 0, 0, i, false);
                    nodeList.add(node);
                }
                //增加节点
                ThinkNode lastNode = parent.getChildren().get(childCount - 1);
                ThinkNode newNode = createNode(parent, (parent.getLevel() + 1) + "-" + childCount, parent.getLevel() + 1, lastNode.getX(), lastNode.getY() + lastNode.getPadding() + verticalSpace + lastNode.getPadding() + wh[1], childCount, childText, false, false);
                parent.getChildren().add(newNode);
                nodeList.add(newNode);
                break;
        }
        redrawChildrenNodes(originNode);
//        redrawSelfNode(originNode);
        postInvalidate();
    }

    public void redrawChildrenNodes(ThinkNode node) {
        moveChildrenNodes(node);
    }

    /**
     * 移动当前节点的子节点
     *
     * @param parentNode 子节点对应的父节点
     */
    private void moveChildrenNodes(ThinkNode parentNode) {
        List<ThinkNode> children = parentNode.getChildren();
        int size = children.size();
        if (size == 0) {
            return;
        }
        for (int i = 0; i < size; i++) {
            ThinkNode child = children.get(i);
            //水平线上方节点
            if (child.getY() <= parentNode.getY()) {
                moveTopNodeOfCurrent(child);
            }
            //水平线下方节点
            if (child.getY() >= parentNode.getY()) {
                moveBelowNodeOfCurrent(child);
            }
        }
    }


    /**
     * 移动上方节点
     *
     * @param currentNode 当前节点
     */
    private void moveTopNodeOfCurrent(ThinkNode currentNode) {
        if (currentNode != null) {
            ThinkNode topNode = findSameLevelTopNode(currentNode);
            if (topNode != null) {
                //水平节点上方节点向上移动
                float currentChildrenOffset[] = measureAllChildrenVerticalOffset(currentNode);
                float topChildrenOffset[] = measureAllChildrenVerticalOffset(topNode);
                float topDistance[] = measureDistance(topNode, currentNode);
                float offsetHeight = currentChildrenOffset[0] + topChildrenOffset[1];
                float offset = offsetHeight - topDistance[1];
                offset = offsetHeight == 0 ? 0 : offset;
                float incremental = verticalSpace;
                if (!topNode.isHorizontal()) {
                    modifyNode(topNode, topNode.getId(), topNode.getLevel(), topNode.getX(), topNode.getY() - offset - incremental, offset, topNode.getOffsetBelow(), topNode.getPosition(), topNode.isHorizontal());
                    moveTopNodeOfCurrent(topNode);
                    redrawChildrenNodes(topNode);
                }
            } else {
                //在子节点有2个，修改上方节点
                ThinkNode parentNode = currentNode.getParent();
                float currentChildrenOffset[] = measureChildrenVerticalOffset(currentNode);
                float topDistance[] = measureDistance(currentNode, parentNode);
                float offsetHeight = currentChildrenOffset[1] + nodeHeight;
                float offset = offsetHeight - topDistance[1];
                offset = offsetHeight == 0 ? 0 : offset;
                float incremental = verticalSpace;
                List<ThinkNode> children = parentNode.getChildren();
                if (children.size() == 2 && childrenSize(children.get(0)) > 1) {
                    modifyNode(currentNode, currentNode.getId(), currentNode.getLevel(), currentNode.getX(), currentNode.getY() - offset - incremental, offset, currentNode.getOffsetBelow(), currentNode.getPosition(), currentNode.isHorizontal());
                }
            }

        }
    }

    /**
     * 移动下方节点
     *
     * @param currentNode 当前节点
     */
    private void moveBelowNodeOfCurrent(ThinkNode currentNode) {
        if (currentNode != null) {
            ThinkNode belowNode = findSameLevelBelowNode(currentNode);
            if (belowNode != null) {
                float currentChildrenOffset[] = measureAllChildrenVerticalOffset(currentNode);
                float belowChildrenOffset[] = measureAllChildrenVerticalOffset(belowNode);
                float belowDistance[] = measureDistance(currentNode, belowNode);
                float offsetHeight = currentChildrenOffset[1] + belowChildrenOffset[0];
                float offset = offsetHeight - belowDistance[1];
                offset = offsetHeight == 0 ? 0 : offset;
                float incremental = verticalSpace;
                if (!belowNode.isHorizontal()) {
                    modifyNode(belowNode, belowNode.getId(), belowNode.getLevel(), belowNode.getX(), belowNode.getY() + offset + incremental, currentNode.getOffsetTop(), offset, belowNode.getPosition(), belowNode.isHorizontal());
                    moveBelowNodeOfCurrent(belowNode);
                    redrawChildrenNodes(currentNode);
                }
            } else {
                //子节点有2个，修改下面节点
                ThinkNode parentNode = currentNode.getParent();
                List<ThinkNode> children = parentNode.getChildren();
                if (children.size() == 2 && childrenSize(children.get(1)) > 1) {
                    float currentChildrenOffset[] = measureChildrenVerticalOffset(currentNode);
                    float topDistance[] = measureDistance(parentNode, currentNode);
                    float offsetHeight = currentChildrenOffset[0] + nodeHeight;
                    float offset = offsetHeight - topDistance[1];
                    offset = offsetHeight == 0 ? 0 : offset;
                    float incremental = verticalSpace;
                    modifyNode(currentNode, currentNode.getId(), currentNode.getLevel(), currentNode.getX(), currentNode.getY() + offset + incremental, currentNode.getOffsetTop(), offset, currentNode.getPosition(), currentNode.isHorizontal());
                }
            }
        }
    }

    /**
     * 重绘自身节点
     *
     * @param node
     */
    public void redrawSelfNode(ThinkNode node) {
        moveSelfNode(node);
    }


    /**
     * 移动当前节点
     *
     * @param node 节点
     */
    private void moveSelfNode(ThinkNode node) {
        List<ThinkNode> children = node.getChildren();
        int size = children.size();
        if (size == 0) {
            return;
        }
        for (int i = 0; i < size; i++) {
            ThinkNode child = children.get(i);
            //水平线上方节点
            if (child.getY() <= node.getY()) {
                moveTopAllNode(child);
            }
            //水平线下方节点
            if (child.getY() >= node.getY()) {
                moveBelowAllNode(child);
            }
        }
    }

    /**
     * 移动上方节点
     *
     * @param currentNode 当前节点
     */
    private void moveTopAllNode(ThinkNode currentNode) {
        if (currentNode != null) {
            ThinkNode topNode = findSameLevelTopNode(currentNode);
            if (topNode != null) {
                //水平节点上方节点向上移动
                float offsetHeight = measureAllChildrenVerticalOffset(currentNode)[0] + measureAllChildrenVerticalOffset(topNode)[1];
                float offset = offsetHeight - measureDistance(topNode, currentNode)[1];
                offset = offsetHeight == 0 ? 0 : offset;
                float incremental = verticalSpace;
                if (!topNode.isHorizontal()) {
                    modifyNode(topNode, topNode.getId(), topNode.getLevel(), topNode.getX(), topNode.getY() - offset - incremental, offset, topNode.getOffsetBelow(), topNode.getPosition(), topNode.isHorizontal());
                    moveTopAllNode(topNode);
                }
            } else {//在子节点有2个，修改上方节点
                ThinkNode parentNode = currentNode.getParent();
                List<ThinkNode> children = parentNode.getChildren();
                if (children.size() == 2 && childrenSize(children.get(0)) != 0) {
                    float topDistance[] = measureDistance(currentNode, parentNode);
                    float offsetHeight = measureAllChildrenVerticalOffset(currentNode)[1] + nodeHeight;
                    float offset = offsetHeight - topDistance[1];
                    offset += currentNode.getOffsetTop();
                    float incremental = verticalSpace;
                    modifyNode(currentNode, currentNode.getId(), currentNode.getLevel(), currentNode.getX(), currentNode.getY() - offset - incremental, offset, currentNode.getOffsetBelow(), currentNode.getPosition(), currentNode.isHorizontal());
                }
            }
        }
    }

    /**
     * 移动下方节点
     *
     * @param currentNode 当前节点
     */
    private void moveBelowAllNode(ThinkNode currentNode) {
        if (currentNode != null) {
            ThinkNode belowNode = findSameLevelBelowNode(currentNode);
            if (belowNode != null) {
                float offsetHeight = measureAllChildrenVerticalOffset(currentNode)[1] + measureAllChildrenVerticalOffset(belowNode)[0];
                float offset = offsetHeight - measureDistance(currentNode, belowNode)[1];
                offset = offsetHeight == 0 ? 0 : offset;
                float incremental = verticalSpace;
                if (!belowNode.isHorizontal()) {
                    modifyNode(belowNode, belowNode.getId(), belowNode.getLevel(), belowNode.getX(), belowNode.getY() + offset + incremental, belowNode.getOffsetTop(), offset, belowNode.getPosition(), belowNode.isHorizontal());
                    moveBelowAllNode(belowNode);
                }
            } else {
                //子节点有2个，修改下面节点
                ThinkNode parentNode = currentNode.getParent();
                List<ThinkNode> children = parentNode.getChildren();
                if (children.size() == 2 && childrenSize(children.get(1)) != 0) {
                    float currentChildrenOffset[] = measureAllChildrenVerticalOffset(currentNode);
                    float topDistance[] = measureDistance(parentNode, currentNode);
                    float offsetHeight = currentChildrenOffset[0] + nodeHeight;
                    float offset = offsetHeight - topDistance[1];
                    offset = offsetHeight == 0 ? 0 : offset;
                    float incremental = verticalSpace;
                    modifyNode(currentNode, currentNode.getId(), currentNode.getLevel(), currentNode.getX(), currentNode.getY() + offset + incremental, currentNode.getOffsetTop(), offset, currentNode.getPosition(), currentNode.isHorizontal());
                }
                //递归修改子节点
                for (int i = 0; i < parentNode.getChildren().size(); i++) {
                    moveSelfNode(parentNode.getChildren().get(i));
                }
            }
        }
    }


    /**
     * 计算子节点Y轴偏移量
     *
     * @param parent 父节点
     * @return 上下偏移量
     */
    public float[] measureChildrenVerticalOffset(ThinkNode parent) {
        return new float[]{measureChildrenTopHeight(parent), measureChildrenBelowHeight(parent)};
    }

    /**
     * 计算子节点的上方高度
     *
     * @param parent
     * @return
     */
    public float measureChildrenTopHeight(ThinkNode parent) {
        if (parent == null) {
            return 0F;
        }
        List<ThinkNode> children = parent.getChildren();
        int size = children.size();
        if (size > 1) {
            ThinkNode node = children.get(0);
            return parent.getRbY() - node.getLtY();
        }
        if (size <= 1) {
            return parent.getHeight();
        }
        return 0F;
    }

    /**
     * 计算子节点的下方高度
     *
     * @param parent
     * @return
     */
    public float measureChildrenBelowHeight(ThinkNode parent) {
        if (parent == null) {
            return 0F;
        }
        List<ThinkNode> children = parent.getChildren();
        int size = children.size();
        if (size > 1) {
            ThinkNode node = children.get(size - 1);
            return node.getRbY() - parent.getLtY();
        }
        if (size <= 1) {
            return parent.getHeight();
        }
        return 0F;
    }

    /**
     * 计算两个节点的距离
     *
     * @param startNode 开始节点
     * @param endNode   结束节点
     * @return x距离  y距离
     */
    public float[] measureDistance(ThinkNode startNode, ThinkNode endNode) {
        if (startNode == null || endNode == null) {
            return new float[]{0F, 0F};
        }
        float x = Math.abs(endNode.getRbX() - startNode.getLtX());
        float y = Math.abs(endNode.getRbY() - startNode.getLtY());
        return new float[]{x, y};
    }

    /**
     * 计算子所有节点Y轴偏移量
     *
     * @param parent 父节点
     * @return 上下偏移量
     */
    public float[] measureAllChildrenVerticalOffset(ThinkNode parent) {
        return new float[]{measureAllChildrenTopHeight(parent), measureAllChildrenBelowHeight(parent)};
    }

    /**
     * 计算所有子节点的上方高度
     *
     * @param parent
     * @return
     */
    public float measureAllChildrenTopHeight(ThinkNode parent) {
        if (parent == null) {
            return 0F;
        }
        ThinkNode topNode = findChildrenFirstNode(parent);
        Log.e("RRL", "====measureAllChildrenTopHeight====>topNode:" + topNode.getText() + ",parent：" + parent.getText());
        return measureDistance(topNode, parent)[1];
    }

    /**
     * 计算所有子节点的下方高度
     *
     * @param parent
     * @return
     */
    public float measureAllChildrenBelowHeight(ThinkNode parent) {
        if (parent == null) {
            return 0F;
        }
        ThinkNode belowNode = findChildrenLastNode(parent);
        Log.e("RRL", "====measureAllChildrenBelowHeight====>belowNode:" + belowNode.getText() + ",parent：" + parent.getText());
        return measureDistance(parent, belowNode)[1];
    }

    /**
     * 找到子节点的最上层节点
     *
     * @param node
     * @return
     */
    public ThinkNode findChildrenFirstNode(ThinkNode node) {
        if (node == null) {
            return null;
        }
        //获取当前及节点的子节点
        List<ThinkNode> children = node.getChildren();
        if (children.size() != 0) {//有子节点
            //获取最上层子节点
            ThinkNode topNode = children.get(0);
            if (topNode.getChildren().size() == 0) {
                return topNode;
            } else {
                return findChildrenFirstNode(topNode);
            }
        }
        return node;
    }

    /**
     * 找到子节点的最下层节点
     *
     * @param node
     * @return
     */
    public ThinkNode findChildrenLastNode(ThinkNode node) {
        if (node == null) {
            return null;
        }
        List<ThinkNode> children = node.getChildren();
        if (children.size() != 0) {
            ThinkNode belowNode = children.get(children.size() - 1);
            if (belowNode.getChildren().size() == 0) {
                return belowNode;
            } else {
                return findChildrenLastNode(belowNode);
            }
        }
        return node;
    }

    /**
     * 子节点个数
     *
     * @param parent
     * @return
     */
    public int childrenSize(ThinkNode parent) {
        if (parent == null) {
            return 0;
        }
        return parent.getChildren().size();
    }

    /**
     * 子节点集合
     *
     * @param parent
     * @return
     */
    public List<ThinkNode> children(ThinkNode parent) {
        if (parent == null) {
            return null;
        }
        return parent.getChildren();
    }

    /**
     * 找到相对一级节点的最上层节点
     *
     * @param node
     * @return
     */
    public ThinkNode findRelativeFirstLevelTopNode(ThinkNode node) {
        if (node == null) {
            return null;
        }
        List<ThinkNode> children = node.getChildren();
        if (children.size() != 0) {
            findRelativeFirstLevelTopNode(children.get(0));
        }
        return node;
    }

    /**
     * 找到相对一级节点的最下层节点
     *
     * @param node
     * @return
     */
    public ThinkNode findRelativeFirstLevelBelowNode(ThinkNode node) {
        if (node == null) {
            return null;
        }
        List<ThinkNode> children = node.getChildren();
        if (children.size() != 0) {
            findRelativeFirstLevelBelowNode(children.get(children.size() - 1));
        }
        return node;
    }

    /**
     * 找到同等级的水平节点
     *
     * @param node
     * @return
     */
    public ThinkNode findSameLevelHorizontalNode(ThinkNode node) {
        if (node == null) {
            return null;
        }
        ThinkNode parent = node.getParent();
        if (parent == null) {
            return null;
        }
        List<ThinkNode> children = parent.getChildren();
        for (int i = 0; i < children.size(); i++) {
            ThinkNode child = children.get(i);
            if (child.isHorizontal()) {
                return child;
            }
        }
        return null;
    }

    /**
     * 找到当前节点的上方节点
     *
     * @param currentNode 当前节点
     * @return
     */
    public ThinkNode findTopNode(ThinkNode currentNode) {
        //找到同等级的上方节点，同父节点
        ThinkNode sameLevelTopNode = findSameLevelTopNode(currentNode);
        if (sameLevelTopNode != null) {
            return sameLevelTopNode;
        }
        ThinkNode parentNode = currentNode.getParent();
        if (parentNode != null) {
            //找到父级节点的上方节点0
            ThinkNode parentTopNode = findSameLevelTopNode(parentNode);
            if (parentTopNode != null) {
                List<ThinkNode> children = parentTopNode.getChildren();
                if (children.size() == 0) {
                    return parentTopNode;
                }
                return children.get(children.size() - 1);
            }
        }
        return null;
    }

    /**
     * 找到当前节点的下方节点
     *
     * @param currentNode 当前节点
     * @return
     */
    public ThinkNode findBelowNode(ThinkNode currentNode) {
        //找到同等级的下方节点，同父节点
        ThinkNode sameLevelBelowNode = findSameLevelBelowNode(currentNode);
        if (sameLevelBelowNode != null) {
            return sameLevelBelowNode;
        }
        if (sameLevelBelowNode == null) {
            ThinkNode parentNode = currentNode.getParent();
            if (parentNode != null) {
                //找到父级节点的下方节点
                ThinkNode parentBelowNode = findSameLevelBelowNode(parentNode);
                if (parentBelowNode != null) {
                    List<ThinkNode> children = parentBelowNode.getChildren();
                    if (children.size() == 0) {
                        return parentBelowNode;
                    }
                    return children.get(0);
                }
            }
        }
        return null;
    }

    /**
     * 找到同等级上方节点
     *
     * @param node
     * @return
     */
    public ThinkNode findSameLevelTopNode(ThinkNode node) {
        if (node == null) {
            return null;
        }
        if (node.isOrigin()) {
            return null;
        }
        return findSameLevelNode(node, node.getPosition() - 1);
    }

    /**
     * 找到同等级下方节点
     *
     * @param node
     * @return
     */
    public ThinkNode findSameLevelBelowNode(ThinkNode node) {
        if (node == null) {
            return null;
        }
        if (node.isOrigin()) {
            return null;
        }
        return findSameLevelNode(node, node.getPosition() + 1);
    }

    /**
     * 查找同等级的
     *
     * @param node     当前节点
     * @param position 查找节点位置
     * @return
     */
    public ThinkNode findSameLevelNode(ThinkNode node, int position) {
        if (node == null) {
            return null;
        }
        if (findSameLevelAllNodes(node) == null) {
            return null;
        }
        if (findSameLevelAllNodes(node).size() == 0) {
            return null;
        }
        if (position < 0 || position >= findSameLevelAllNodes(node).size()) {
            return null;
        }
        return findSameLevelAllNodes(node).get(position);
    }

    /**
     * 找到同等级的所有节点
     *
     * @param node
     * @return
     */
    public List<ThinkNode> findSameLevelAllNodes(ThinkNode node) {
        if (node == null) {
            return null;
        }
        ThinkNode parent = node.getParent();
        if (parent == null) {
            return null;
        }
        return parent.getChildren();
    }


    /**
     * 结算父节点下面的所有子节点的高度
     *
     * @param parent 父节点
     * @return
     */
    public float measureChildrenHeight(ThinkNode parent) {
        if (parent == null) {
            return 0F;
        }
        List<ThinkNode> children = parent.getChildren();
        int size = children.size();
        if (size == 1) {
            ThinkNode node = children.get(0);
            return node.getRbY() - node.getLtY();
        }
        if (size > 1) {
            ThinkNode firstNode = children.get(0);
            ThinkNode lastNode = children.get(size - 1);
            return lastNode.getRbY() - firstNode.getLtY();
        }
        return 0F;
    }


    /**
     * 通过坐标找到控件
     *
     * @param x 横向坐标值
     * @param y 纵向坐标值
     * @return
     */
    public ThinkNode findNode(float x, float y) {
        int size = nodeList.size();
        if (size == 0) {
            return null;
        }
        for (int i = 0; i < size; i++) {
            ThinkNode node = nodeList.get(i);
            if (isScope(node, x, y)) {
                return node;
            }
        }
        return null;
    }

    /**
     * 是否是范围坐标
     *
     * @param node
     * @param x
     * @param y
     * @return
     */
    public boolean isScope(ThinkNode node, float x, float y) {
        if (node == null) {
            return false;
        }
        if (node.getLtX() <= x && node.getRbX() >= x && node.getLtY() <= y && node.getRbY() >= y) {
            return true;
        }
        return false;
    }

    /**
     * 节点点击监听
     */
    public OnNodeClickListener listener;

    /**
     * 设置节点点击事件
     *
     * @param listener
     */
    public void setOnNodeClickListener(OnNodeClickListener listener) {
        this.listener = listener;
    }

    /**
     * 节点点击监听
     */
    public interface OnNodeClickListener {
        void onNodeClick(ThinkNode node);
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downX = event.getX();
                downY = event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                moveX += event.getX() - downX;
                moveY += event.getY() - downY;
                if (Math.abs(moveX) > 10) {
                    setTranslationX(moveX);
                }
                if (Math.abs(moveY) > 10) {
                    setTranslationY(moveY);
                }
                break;
            case MotionEvent.ACTION_UP:
                clickNode = findNode(event.getX(), event.getY());
                if (clickNode != null && listener != null) {
                    listener.onNodeClick(clickNode);
                }
                break;
        }
        return true;
    }

}
